package com.tanhua.server.service;

import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitors;
import com.tanhua.domain.vo.MovementsVo;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.VisitorsVo;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.PublishApi;
import com.tanhua.dubbo.api.mongo.VisitorsApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.RelativeDateFormat;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;
    @Reference
    public PublishApi publishApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    /**
     * 接口名称：动态-发布
     * 接口路径：POST/movements
     * 需求分析：发布动态，需要往动态表、自己的相册表、好友的时间线表存储发布动态的内容
     */
    public ResponseEntity<Object> saveMovements(
            Publish publish, MultipartFile[] imageContent) throws IOException {
        //1. 获取登陆用户id, 当前登陆用户发布的动态
        Long userId = UserHolder.getUserId();

        //2. 处理动态中的图片:把数组转换为List集合
        List<String> mediasList = new ArrayList<>();
        if (imageContent != null && imageContent.length>0) {
            for (MultipartFile file : imageContent) {
                // 处理图片上传到阿里云OSS
                String url = ossTemplate.upload(file.getOriginalFilename(),
                        file.getInputStream());
                mediasList.add(url);
            }
        }
        //3. 把封装好的图片集合设置到动态对象中
        publish.setMedias(mediasList);

        //4. 保存发布的动态
        publish.setUserId(userId);
        publish.setCreated(System.currentTimeMillis());
        // 设置状态为未审核
        publish.setState(0);
        // 设置动态id
        publish.setId(ObjectId.get());
        publishApi.save(publish);

        try {
            // 发送mq消息，携带动态id
            rocketMQTemplate.convertAndSend("tanhuan-publish-151",publish.getId().toString());
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：好友动态
     * 接口路径：GET/movements
     * 需求分析：查询好友动态，就是查看“朋友圈”。在自己的时间线表中存储了所有好友的动态
     * 举例：登陆用户id是1，查询好友动态就是查询 db.quanzi_time_line_1.find()
     */
    public ResponseEntity<Object> queryPublishList(Integer page, Integer pagesize) {
        //1. 获取用户id
        Long userId = UserHolder.getUserId();
        //2. 根据用户id分页查询好友动态(在Api服务中查询时间线表，经过处理后返回动态数据)
        PageResult pageResult = publishApi.findByTimeLine(page,pagesize,userId);
        // 调用方法封装vo，并最终设置到pageResult中
        setMovementsVo(pageResult);
        // 返回响应
        return ResponseEntity.ok(pageResult);
    }

    private void setMovementsVo(PageResult pageResult) {
        //3. 获取分页中的动态数据
        List<Publish> publishList = (List<Publish>) pageResult.getItems();
        //4. 封装返回的vo集合
        List<MovementsVo> voList = new ArrayList<>();
        //5. 遍历动态集合publishList, 封装voList
        if (publishList != null && publishList.size()>0) {
            for (Publish publish : publishList) {
                // 创建vo对象
                MovementsVo vo = new MovementsVo();
                this.convertPublishToMovements(publish,vo);
                // 把封装好的vo添加到集合
                voList.add(vo);
            }
        }

        // 把处理好的vo集合设置到分页对象中
        pageResult.setItems(voList);
    }

    // 工具类：把publish转换为MovementsVo对象
    public void convertPublishToMovements(Publish publish,MovementsVo vo){
        // 根据用户id查询
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        if (userInfo != null) {
            BeanUtils.copyProperties(userInfo,vo);
            if (userInfo.getTags() != null) {
                vo.setTags(userInfo.getTags().split(","));
            }
        }
        // 对象拷贝：publish-->vo
        BeanUtils.copyProperties(publish,vo);

        // 设置动态id、动态的图片
        vo.setId(publish.getId().toString());
        vo.setImageContent(publish.getMedias().toArray(new String[]{}));

        // 设置距离
        vo.setDistance("50米");
        // 设置时间如：5小时之前
        vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

        if (redisTemplate.hasKey("public_like_comment_"+UserHolder.getUserId()+"_"+vo.getId())) {
            vo.setHasLiked(1);
        } else {
            vo.setHasLiked(0);
        }

        if (redisTemplate.hasKey("public_love_comment_"+UserHolder.getUserId()+"_"+vo.getId())) {
            vo.setHasLoved(1);
        } else {
            vo.setHasLoved(0);
        }
    }

    /**
     * 接口名称：推荐动态
     * 接口路径：GET/movements/recommend
     * 查询的表：recommend_quanzi
     */
    public ResponseEntity<Object> queryRecommendPublishList(Integer page, Integer pagesize) {
        //1. 获取用户id
        Long userId = UserHolder.getUserId();
        // 【修改查询：推荐动态，首先从redis查询，没有查询到推荐系统推荐的数据，再查询mongo】
        PageResult pageResult = findByRecommend(page,pagesize,userId);
        // 如果没有找到，就查询mongo
        if (pageResult == null) {
            //2. 根据用户id分页查询好友动态(在Api服务中查询时间线表，经过处理后返回动态数据)
            pageResult = publishApi.queryRecommendPublishList(page, pagesize, userId);
        }
        // 调用方法封装vo，并最终设置到pageResult中
        setMovementsVo(pageResult);
        // 返回响应
        return ResponseEntity.ok(pageResult);
    }

    // 查询redis中推荐动态
    private PageResult findByRecommend(Integer page, Integer pagesize, Long userId) {
        //1. 拼接redis中的key
        String key = "QUANZI_PUBLISH_RECOMMEND_" + userId;
        //2. 根据key获取推荐用户:  100092,82,18,20,20,22,23,25,24,33
        String value = redisTemplate.opsForValue().get(key);
        //3. 判断
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        //4. 分割字符串  100092 82 18 20 20 22 23 25 24 33
        String[] pids = value.split(",");
        int counts = pids.length;
        // 查询的起始
        int startIndex = (page - 1) * pagesize;
        if(startIndex < pids.length) { //起始条数小于数据总数
            int endIndex = startIndex + pagesize - 1;
            if (endIndex >= pids.length) {
                endIndex = pids.length - 1;
            }
            List<Long> pidList = new ArrayList<>();   //本页查询的所有动态的pid列表
            for (int i = startIndex; i <= endIndex; i++) {
                pidList.add(Long.valueOf(pids[i]));
            }
            //本次分页的数据列表
            List<Publish> list = publishApi.findByPids(pidList);
            return new PageResult(page, pagesize, counts, list);
        }
        return null;
    }

    /**
     * 接口名称：用户动态(我的动态)
     */
    public ResponseEntity<Object> queryAlbumPublishList(Integer page, Integer pagesize) {
        Long userId=UserHolder.getUserId();
        PageResult pageResult=publishApi.queryAlbumPublishList(page,pagesize,userId);
        this.setMovementsVo(pageResult);
        return ResponseEntity.ok(pageResult);
    }

    @Reference
    private VisitorsApi visitorsApi;

    /**
     * 接口名称：谁看过我
     */
    public ResponseEntity<Object> queryVisitors() {
        //1. 获取用户id
        Long userId = UserHolder.getUserId();

        // 存储到redis中的登陆时间的key
        String key = "visitors_time_"+userId;
        // 从redis中获取上一次访问时间
        String time = redisTemplate.opsForValue().get(key);

        List<Visitors> visitorsList = null;
        //2. 查询最近访客
        if (StringUtils.isEmpty(time)) {
            //2.1 第一次登陆系统，默认显示最近5个访客.  记录当前时间为 100
            visitorsList = visitorsApi.queryVisitors(userId, 5);
        } else {
            //2.2 再次登陆,显示最近的访客  date > 100
            visitorsList = visitorsApi.queryVisitors(userId, Long.parseLong(time));
        }

        // 保存当前登陆时间到redis
        redisTemplate.opsForValue().set(key,System.currentTimeMillis()+"");

        //3. 封装返回结果
        List<VisitorsVo> voList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(visitorsList)) {
            for (Visitors visitors : visitorsList) {
                // 创建并封装vo对象
                VisitorsVo vo = new VisitorsVo();
                vo.setId(visitors.getVisitorUserId());
                // 根据访客id查询
                UserInfo userInfo = userInfoApi.findById(visitors.getVisitorUserId());
                if (userInfo != null) {
                    BeanUtils.copyProperties(userInfo,vo);
                    if (userInfo.getTags() != null) {
                        vo.setTags(userInfo.getTags().split(","));
                    }
                }
                // 设置缘分值
                vo.setFateValue(visitors.getScore().intValue());

                // 添加到集合
                voList.add(vo);
            }
        }

        return ResponseEntity.ok(voList);
    }


}




















